/*
 * Copyright 2003 Program of Computer Graphics, Cornell University
 *     580 Rhodes Hall
 *     Cornell University
 *     Ithaca NY 14853
 * Web: http://www.graphics.cornell.edu/
 * 
 * Not for commercial use. Do not redistribute without permission.
 */

#ifndef _H_EXPANDABLE_ARRAY
#define _H_EXPANDABLE_ARRAY


template <class T> class ExpandableArray {
  int usedSize;
  int allocSize;
  T *array;

  void growArray(int newSize) {
    assert(newSize>=usedSize);
    T *newArray = new T[newSize];
    assert(newArray);
    memcpy(newArray,array,sizeof(T)*usedSize);
    delete[] array;
    array = newArray;
    allocSize = newSize;
  }
public:
  ExpandableArray() { usedSize = allocSize = 0; array = NULL; }
  ExpandableArray(int size) { usedSize = 0; allocSize = size; array = new T[size]; assert(array); }
  ExpandableArray(const ExpandableArray<T> &copy, bool copyContents) {
    array = new T[copy.usedSize];
    assert(array);
    allocSize = copy.usedSize;
    if (copyContents) {
      memcpy(array,copy.array,sizeof(T)*copy.usedSize);
      usedSize = copy.usedSize;
    } else { //if not copying contents, then we just copy the capacity, but leave at zero length
      usedSize = 0;
    }
  }
  ~ExpandableArray() { if (array) delete[] array; }

  int size() const { return usedSize; }
  void ensureCapacity(int numElements) 
  { if (numElements > allocSize) growArray(numElements); }
  /*
  void setSize(int newSize) { //contents undefined if newSize > oldSize
    if (newSize > allocSize) growArray(newSize);
    usedSize = newSize;
  }
  */
  void append(T a) {
    if (usedSize == allocSize) growArray(usedSize+8+(usedSize>>1));
    array[usedSize++] = a;
  }
  void removeAll() { usedSize = 0; }
  void copyFrom(const ExpandableArray<T> &copy) {
    if (allocSize < copy.usedSize) growArray(copy.usedSize);
    memcpy(array,copy.array,sizeof(T)*copy.usedSize);
    usedSize = copy.usedSize;
  }
  const T&operator[](int index) const { return array[index]; }
  T &operator[](int index) { return array[index]; }
};

#endif /* _H_EXPANDABLE_ARRAY */

